package com.allwees.bs.c.module.base.aop;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.allwees.bs.c.module.user.entity.UsrActiveLog;
import com.allwees.bs.c.module.user.service.UserActiveLogService;
import com.allwees.bs.core.model.constant.CacheName;
import com.allwees.bs.core.model.user.context.CurrentUser;
import com.allwees.bs.core.modelbase.req.Req;
import com.allwees.core.cache.RedisUtil;
import com.allwees.core.common.constant.EPlatform;
import com.allwees.core.common.util.DateUtil;
import com.allwees.core.common.util.http.RequestContext;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * RestController拦截器
 *
 * @author yangylsky
 * @since 2019-09-23
 *
 */
@Slf4j
@Aspect
@Component
public class RestAspect {

	@Resource
	private UserActiveLogService userActiveLogService;

	@Pointcut("@within(org.springframework.web.bind.annotation.RestController)")
	public void pointcut() {
	}

	@Around("pointcut()")
	public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
		Object[] params = joinPoint.getArgs();
		for(Object param : params) {
			if(param instanceof Req){
				((Req) param).validate();
			}
		}
		Object retObj = joinPoint.proceed();
		markCustomerAsActivity();
		return retObj;
	}

	private static final long TTL = 24 * 3600L;
	/**
	 *
	 */
	private static final Pattern APP_VERSION_PATTERN = Pattern.compile(".*?(\\d+\\.\\d+\\.\\d+).*");
	/**
	 * 标记活跃用户
	 */
	private void markCustomerAsActivity(){
		CurrentUser user = CurrentUser.getUser(false);
		if (user == null) {
			return;
		}
		String userUuid = user.getUserUuid();

		try {
			int today = Integer.parseInt(DateUtil.formatDate(new Date(), "yyyyMMdd"));
			String key = String.format(CacheName.USER_ACTIVE_KEY_PREFIX, today);
			boolean success = RedisUtil.putIfAbsent(key, userUuid, 1, TTL);
			if (!success) {
				return;
			}

			LambdaQueryChainWrapper<UsrActiveLog> lambdaQuery = userActiveLogService.lambdaQuery();
			lambdaQuery.eq(UsrActiveLog::getUserUuid, userUuid);
			lambdaQuery.eq(UsrActiveLog::getActiveDay, today);
			int count = lambdaQuery.count();
			if (count > 0) {
				return;
			}
			UsrActiveLog activeLog = new UsrActiveLog();
			activeLog.setUserUuid(userUuid);
			activeLog.setActiveDay(today);
			EPlatform platform = RequestContext.getPlatform();
			activeLog.setPlatform(platform);
			String appVersion = RequestContext.getAppVersion();
			if (StringUtils.isNotBlank(appVersion)) {
				Matcher matcher = APP_VERSION_PATTERN.matcher(appVersion);
				if (matcher.matches()) {
					appVersion = matcher.group(1);
				}
			}
			activeLog.setAppVersion(appVersion);
			userActiveLogService.save(activeLog);
		} catch (Exception e) {
			log.error("markAsActivity error.",e);
		}
	}
}
